// SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
// SPDX-License-Identifier: Mulan PSL v2
package interceptor

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"code.geniusai.org/notebook-manager/pkg/config"
	"code.geniusai.org/notebook-manager/pkg/handler"
	"github.com/gin-gonic/gin"
)

var resJson struct {
	Code    string `json:"code"`
	Msg     string `json:"msg"`
	Success bool   `json:"success"`
}

/*
*

	覆盖率检查：go test -v -cover
	生成测试报告：go test -covermode=count -coverprofile=coverprofile.cov -run="_test" -coverpkg="./"
	html查看报告：go tool cover -html=coverprofile.cov
*/
func setup() {
	gin.SetMode(gin.TestMode)
	fmt.Println("Before all tests")
}

func teardown() {
	fmt.Println("After all tests")
}
func TestMain(m *testing.M) {
	setup()
	fmt.Println("Test begins....")
	code := m.Run()
	teardown()
	os.Exit(code)
}

func SetupRouter() *gin.Engine {
	router := gin.Default()
	notebookV1 := router.Group("/notebooks/v1")
	mockHttpInterceptorInterface := &MockHttpInterceptorInterface{}
	notebookV1.Use(NewHttpInterceptor(mockHttpInterceptorInterface, config.Conf{}).Interceptor())
	notebookHandler := NewMockNotebookHandler()
	notebookV1.POST("/users/:userID/notebooks", handler.Wrapper(notebookHandler.Create))
	notebookV1.POST("/notebooks/:id/start", handler.Wrapper(notebookHandler.Start))
	notebookV1.POST("/notebooks/show-cpu-usage", handler.Wrapper(notebookHandler.ShowCpuUsage))
	notebookV1.POST("/notebooks/:id", handler.Wrapper(notebookHandler.Modify))
	return router
}

func TestInterceptor_UserID_SUCCESS_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "", "", "exist_user_id", "", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "0000000" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_ID_SUCCESS_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "", "", "", "exist_ID", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "0000000" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Post_ID_SUCCESS_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "", "exist_ID", "", "", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "0000000" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Post_UserID_SUCCESS_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "exist_user_id", "", "", "exist_ID", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "0000000" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Cookie_Nonexistence_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "", "", "exist_user_id", "", "")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030001" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Cookie_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "", "", "exist_user_id", "", "exist_user_id_xxxx")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030002" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_UserID_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "", "", "exist_user_id_xxx", "", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030002" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_ID_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "exist_user_id", "", "", "exist_ID_xx", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030003" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Post_ID_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "", "exist_ID_xx", "", "", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030003" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Post_UserID_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "exist_user_id_xxx", "", "", "exist_ID", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030002" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Post_UserID_1_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "exist_user_id_xxx", "", "exist_user_id_xxx", "", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030002" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Post_UserID_2_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "exist_user_id_xxx", "", "exist_user_id_xxx", "", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030002" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Post_UserID_3_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "exist_user_id_xxx", "", "exist_user_id", "", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030002" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func TestInterceptor_Path_User_ID_Error_test(t *testing.T) {

	router := SetupRouter()

	// 1. given
	req := GivenParam(t, "", "", "exist_user_id", "exist_id", "exist_user_id_cookie")

	// 2. when
	resJson = DoProcess(t, router, req)

	// 3. then
	if resJson.Code != "4030003" {
		t.Fatalf("响应状态码不符合预期")
	}

}

func DoProcess(t *testing.T, router *gin.Engine, req *http.Request) struct {
	Code    string `json:"code"`
	Msg     string `json:"msg"`
	Success bool   `json:"success"`
} {
	rec := httptest.NewRecorder()
	router.ServeHTTP(rec, req)
	result := rec.Result()
	if result.StatusCode == 404 {
		t.Fatalf("请求的URL不存在")
	}
	if result.StatusCode != 200 {
		t.Fatalf("请求状态码不符合预期")
	}
	body, err := ioutil.ReadAll(result.Body)
	if err != nil {
		t.Fatalf("读取返回内容失败, err:%v", err)
	}
	defer result.Body.Close()

	err = json.Unmarshal(body, &resJson)

	if err != nil {
		t.Fatalf("转换结果失败,err: %v", err)
	}
	return resJson
}

func GivenParam(t *testing.T, postUserID string, postID string, pathUserID string, pathID string, cookie string) *http.Request {
	paramId, err := json.Marshal(&ParamID{ID: postID, UserID: postUserID})
	reader := bytes.NewReader(paramId)

	var urlstring string
	if len(pathUserID) != 0 {
		urlstring = "/notebooks/v1/users/" + pathUserID + "/notebooks"
	}
	if len(pathID) != 0 {
		urlstring = "/notebooks/v1/notebooks/" + pathID + "/start"
	}
	if len(postID) != 0 {
		urlstring = "/notebooks/v1/notebooks/show-cpu-usage"
	}
	if len(postUserID) != 0 && len(pathID) != 0 {
		urlstring = "/notebooks/v1/notebooks/" + pathID
	}
	req, err := http.NewRequest(http.MethodPost, urlstring, reader)

	if err != nil {
		t.Fatalf("构建请求失败, err: %v", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Cookie", cookie)
	return req
}
